/*     */ package com.zimbra.cs.mailclient.imap;
/*     */ 
/*     */ import com.zimbra.common.util.Log;
/*     */ import com.zimbra.common.util.ZimbraLog;
/*     */ import com.zimbra.cs.mailclient.MailException;
/*     */ import com.zimbra.cs.mailclient.MailInputStream;
/*     */ import com.zimbra.cs.mailclient.ParseException;
/*     */ import com.zimbra.cs.mailclient.util.Ascii;
/*     */ import com.zimbra.cs.mailclient.util.Io;
/*     */ import com.zimbra.cs.mailclient.util.LimitInputStream;
/*     */ import java.io.ByteArrayOutputStream;
/*     */ import java.io.EOFException;
/*     */ import java.io.File;
/*     */ import java.io.FileOutputStream;
/*     */ import java.io.IOException;
/*     */ import java.io.InputStream;
/*     */ import java.io.OutputStream;
/*     */ import java.io.PrintStream;
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ public final class ImapInputStream
/*     */   extends MailInputStream
/*     */ {
/*     */   private final ImapConnection connection;
/*     */   private final ImapConfig config;
/*     */   private final ByteArrayOutputStream baos;
/*     */   private static final boolean DEBUG = false;
/*     */   
/*     */   public ImapInputStream(InputStream is, ImapConnection connection)
/*     */   {
/*  47 */     super(is);
/*  48 */     this.connection = connection;
/*  49 */     this.config = connection.getImapConfig();
/*  50 */     this.baos = new ByteArrayOutputStream();
/*     */   }
/*     */   
/*     */   public ImapInputStream(InputStream is, ImapConnection connection, Log log) {
/*  54 */     super(is, log);
/*  55 */     this.connection = connection;
/*  56 */     this.config = connection.getImapConfig();
/*  57 */     this.baos = new ByteArrayOutputStream();
/*     */   }
/*     */   
/*     */   public ImapInputStream(InputStream is, ImapConfig config) {
/*  61 */     super(is);
/*  62 */     this.connection = null;
/*  63 */     this.config = config;
/*  64 */     this.baos = new ByteArrayOutputStream();
/*     */   }
/*     */   
/*     */   public Atom readAtom() throws IOException {
/*  68 */     skipSpaces();
/*  69 */     String s = readChars(Chars.ATOM_CHARS);
/*  70 */     if (s.length() == 0) {
/*  71 */       throw new ParseException("Zero-length atom");
/*     */     }
/*     */     
/*  74 */     return new Atom(s);
/*     */   }
/*     */   
/*     */   public Atom readFlag() throws IOException {
/*  78 */     skipSpaces();
/*  79 */     this.sbuf.setLength(0);
/*  80 */     if (peek() == 92) {
/*  81 */       this.sbuf.append((char)read());
/*  82 */       if (peek() == 42) {
/*  83 */         this.sbuf.append((char)read());
/*  84 */         return new Atom(this.sbuf.toString());
/*     */       }
/*     */     }
/*  87 */     int len = this.sbuf.length();
/*  88 */     while (Chars.isAtomChar(peekChar())) {
/*  89 */       this.sbuf.append((char)read());
/*     */     }
/*  91 */     if (this.sbuf.length() - len == 0) {
/*  92 */       throw new ParseException("Invalid flag character '" + Ascii.pp((byte)peek()) + "'");
/*     */     }
/*     */     
/*  95 */     return new Atom(this.sbuf.toString());
/*     */   }
/*     */   
/*     */   public String readString() throws IOException {
/*  99 */     return readStringData().toString();
/*     */   }
/*     */   
/*     */   public ImapData readStringData() throws IOException {
/* 103 */     ImapData as = readAStringData();
/* 104 */     if (!as.isString()) {
/* 105 */       throw new ParseException("Expected STRING but got " + as);
/*     */     }
/* 107 */     return as;
/*     */   }
/*     */   
/*     */   public String readNString() throws IOException {
/* 111 */     ImapData ns = readNStringData();
/* 112 */     return ns.isNil() ? null : ns.toString();
/*     */   }
/*     */   
/*     */   public ImapData readNStringData() throws IOException {
/* 116 */     ImapData as = readAStringData();
/* 117 */     if (!as.isNString()) {
/* 118 */       throw new ParseException("Expected NIL or STRING, but got: " + as);
/*     */     }
/* 120 */     return as;
/*     */   }
/*     */   
/*     */   public Object readFetchData() throws IOException {
/* 124 */     DataHandler handler = getDataHandler();
/* 125 */     if (handler == null) {
/* 126 */       return readNStringData();
/*     */     }
/* 128 */     ImapData as = peek() == 123 ? readLiteral(false) : readNStringData();
/*     */     try {
/* 130 */       return handler.handleData(as);
/*     */     } catch (Throwable e) {
/* 132 */       throw new MailException("Exception in data handler", e);
/*     */     } finally {
/* 134 */       if (as.isLiteral()) {
/* 135 */         skipRemaining(as.getInputStream());
/*     */       }
/*     */     }
/*     */   }
/*     */   
/*     */   private void skipRemaining(InputStream is) throws IOException {
/* 141 */     while (is.skip(8191L) > 0L) {}
/*     */   }
/*     */   
/*     */   private DataHandler getDataHandler() {
/* 145 */     return this.connection != null ? this.connection.getDataHandler() : null;
/*     */   }
/*     */   
/*     */   public String readAString() throws IOException {
/* 149 */     return readAStringData().toString();
/*     */   }
/*     */   
/*     */   public ImapData readAStringData() throws IOException {
/* 153 */     skipSpaces();
/*     */     
/*     */     ImapData as;
/* 156 */     switch (peekChar()) {
/*     */     case '"': 
/* 158 */       as = readQuoted();
/* 159 */       break;
/*     */     case '{': 
/* 161 */       as = readLiteral(true);
/* 162 */       break;
/*     */     default: 
/* 164 */       String s = readChars(Chars.ASTRING_CHARS);
/* 165 */       if (s.length() == 0) {
/* 166 */         throw new ParseException("Zero-length atom");
/*     */       }
/* 168 */       as = new Atom(s);
/*     */     }
/*     */     
/* 171 */     return as;
/*     */   }
/*     */   
/*     */   public boolean isNumber() throws IOException {
/* 175 */     return (!isEOF()) && (Chars.isNumber(peekChar()));
/*     */   }
/*     */   
/*     */   public long readNZNumber() throws IOException {
/* 179 */     return readNumber(true);
/*     */   }
/*     */   
/*     */   public long readNumber() throws IOException {
/* 183 */     return readNumber(false);
/*     */   }
/*     */   
/*     */   private long readNumber(boolean nz) throws IOException {
/* 187 */     skipSpaces();
/* 188 */     String s = readChars(Chars.NUMBER_CHARS);
/* 189 */     if (s.length() == 0) {
/* 190 */       throw new ParseException("Zero-length number");
/*     */     }
/* 192 */     long n = Chars.getNumber(s);
/* 193 */     if (n == -1L) {
/* 194 */       throw new ParseException("Invalid number format: " + s);
/*     */     }
/* 196 */     if ((nz) && (n == 0L)) {
/* 197 */       throw new ParseException("Expected non-zero number but got " + s);
/*     */     }
/*     */     
/* 200 */     return n;
/*     */   }
/*     */   
/*     */   public Quoted readQuoted() throws IOException {
/* 204 */     skipChar('"');
/* 205 */     this.sbuf.setLength(0);
/*     */     int c;
/* 207 */     while ((c = read()) != 34) {
/* 208 */       switch (c) {
/*     */       case 10: case 13: 
/* 210 */         throw new ParseException("Unexpected end of line while reading QUOTED string");
/*     */       
/*     */       case -1: 
/* 213 */         throw new EOFException("Unexpected end of stream while reading QUOTED string");
/*     */       
/*     */       case 92: 
/* 216 */         c = readChar();
/*     */       }
/* 218 */       this.sbuf.append((char)c);
/*     */     }
/* 220 */     return new Quoted(this.sbuf.toString());
/*     */   }
/*     */   
/*     */   private Literal readLiteral(boolean cache) throws IOException {
/* 224 */     skipChar('{');
/* 225 */     long len = readNumber();
/* 226 */     if (len > 2147483647L) {
/* 227 */       throw new ParseException("Literal size too large: " + len);
/*     */     }
/*     */     
/* 230 */     skipSpaces();
/* 231 */     skipChar('}');
/* 232 */     skipCRLF();
/*     */     
/* 234 */     return readLiteral((int)len, cache);
/*     */   }
/*     */   
/*     */   private Literal readLiteral(int len, boolean cache) throws IOException {
/* 238 */     if (!cache) {
/* 239 */       return new Literal(new LimitInputStream(this.in, len), len);
/*     */     }
/* 241 */     if (len <= this.config.getMaxLiteralMemSize())
/*     */     {
/* 243 */       byte[] b = new byte[len];
/* 244 */       Io.readFully(this.in, b);
/* 245 */       return new Literal(b);
/*     */     }
/*     */     
/*     */ 
/* 249 */     File f = File.createTempFile("lit", null, this.config.getLiteralDataDir());
/* 250 */     f.deleteOnExit();
/* 251 */     OutputStream os = new FileOutputStream(f);
/*     */     try {
/* 253 */       Io.copyBytes(this.in, os, len);
/*     */     } finally {
/* 255 */       os.close();
/*     */     }
/* 257 */     return new Literal(f, true);
/*     */   }
/*     */   
/*     */   public String readText() throws IOException {
/* 261 */     if (isEOL()) {
/* 262 */       return "";
/*     */     }
/*     */     
/* 265 */     this.baos.reset();
/*     */     do {
/* 267 */       this.baos.write(read());
/* 268 */     } while (!isEOL());
/* 269 */     return this.baos.toString("UTF8");
/*     */   }
/*     */   
/*     */   public String readText(char delim) throws IOException {
/* 273 */     return readText(String.valueOf(delim));
/*     */   }
/*     */   
/*     */   public String readText(String delims) throws IOException {
/* 277 */     this.sbuf.setLength(0);
/* 278 */     char c = '\000';
/* 279 */     while ((!isEOF()) && (delims.indexOf(c = peekChar()) < 0)) {
/* 280 */       if (!Chars.isTextChar(c)) {
/* 281 */         throw new ParseException("Unexpected character '" + Ascii.pp((byte)c) + "' while reading TEXT string");
/*     */       }
/*     */       
/*     */ 
/* 285 */       this.sbuf.append((char)read());
/*     */     }
/* 287 */     if (this.sbuf.length() == 0) {
/* 288 */       throw new ParseException("Invalid text character '" + Ascii.pp((byte)c) + "'");
/*     */     }
/*     */     
/* 291 */     return this.sbuf.toString();
/*     */   }
/*     */   
/*     */   public String readChars(boolean[] chars) throws IOException {
/* 295 */     this.sbuf.setLength(0);
/* 296 */     while (chars[peekChar()] != 0) {
/* 297 */       this.sbuf.append((char)read());
/*     */     }
/* 299 */     return this.sbuf.toString();
/*     */   }
/*     */   
/*     */   public void skipOptionalChar(char expectedChar) throws IOException {
/* 303 */     char c = peekChar();
/* 304 */     if (c == expectedChar) {
/* 305 */       readChar();
/*     */     }
/*     */   }
/*     */   
/*     */   public void skipChar(char expectedChar) throws ParseException, IOException {
/* 310 */     char c = readChar();
/* 311 */     if (c != expectedChar) {
/* 312 */       throw new ParseException("Unexpected character '" + Ascii.pp((byte)c) + "' (expecting '" + Ascii.pp((byte)expectedChar) + "')");
/*     */     }
/*     */   }
/*     */   
/*     */   public void skipNil()
/*     */     throws IOException
/*     */   {
/* 319 */     Atom atom = readAtom();
/* 320 */     if (!atom.isNil()) {
/* 321 */       throw new ParseException("Expecting NIL but got " + atom);
/*     */     }
/*     */   }
/*     */   
/*     */   public void skipCRLF() throws IOException {
/*     */     try {
/* 327 */       skipSpaces();
/* 328 */       skipChar('\r');
/* 329 */       skipChar('\n');
/*     */     }
/*     */     catch (ParseException pe) {
/* 332 */       ZimbraLog.imap_client.error("ParseException reading EOL", pe);
/*     */       
/* 334 */       while (readChar() != '\n') {}
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   public boolean match(char c)
/*     */     throws IOException
/*     */   {
/* 348 */     if (peek() == c) {
/* 349 */       read();
/* 350 */       return true;
/*     */     }
/* 352 */     return false;
/*     */   }
/*     */   
/*     */   public void skipSpaces() throws IOException {
/* 356 */     while (match(' ')) {}
/*     */   }
/*     */   
/*     */   public boolean isEOL() throws IOException {
/* 360 */     return peek() == 13;
/*     */   }
/*     */   
/*     */   private static void pd(String fmt, Object... args) {
/* 364 */     System.out.print("[DEBUG] ");
/* 365 */     System.out.printf(fmt, args);
/* 366 */     System.out.println();
/*     */   }
/*     */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/mailclient/imap/ImapInputStream.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */